package parser;

import adventure.Adventure;
import adventure.AdventureEdit;
import adventure.AdventureImp;
import adventure.commands.skills.ConjureItem;
import adventure.commands.skills.SingleTargetDamage;
import adventure.commands.skills.SingleTargetHeal;
import adventure.commands.skills.Skill;
import adventure.commands.skills.SkillEdit;
import adventure.misc.CurrencyImp;
import adventure.placeable.Item;
import adventure.placeable.ItemEdit;
import adventure.placeable.ItemImp;
import adventure.placeable.ItemUnlocksEdit;
import adventure.placeable.ItemUnlocksImp;
import adventure.placeable.Mobile;
import adventure.placeable.MobileEdit;
import adventure.placeable.MobileImp;
import adventure.placeable.trigger.Trigger;
import adventure.placeable.trigger.TriggerEdit;
import adventure.placeable.trigger.TriggerImp;
import adventure.placeable.trigger.conditions.PlayerCondition;
import adventure.placeable.trigger.conditions.RoomCondition;
import adventure.placeable.trigger.conditions.StringCondition;
import adventure.placeable.trigger.conditions.TriggerCondition;
import adventure.placeable.trigger.results.ResultModifyPlayer;
import adventure.placeable.trigger.results.ResultModifyRoom;
import adventure.placeable.trigger.results.ResultMovePlayer;
import adventure.placeable.trigger.results.ResultSpawnItem;
import adventure.placeable.trigger.results.ResultSpawnMobile;
import adventure.placeable.trigger.results.ResultSpawnTrigger;
import adventure.placeable.trigger.results.ResultString;
import adventure.placeable.trigger.results.TriggerResult;
import adventure.room.RoomEdit;
import adventure.room.RoomImp;
import adventure.vocation.Vocation;
import adventure.vocation.VocationEdit;
import adventure.vocation.VocationImp;
import java.io.BufferedReader;
import player.BookEntry;
import player.BookEntryEdit;
import player.BookEntryImp;
import player.Player;
import player.PlayerEdit;
import player.PlayerImp;
import player.PlayerManager;
import server.util.Broadcaster;
import server.util.BroadcasterImp;

/**
 *
 * @author Michael Hanns
 *
 */
public class Parser {

    boolean debug = false;
    protected AdventureEdit adv;
    protected PlayerManager players;
    protected Broadcaster out;
    private RoomEdit room;
    private ItemEdit item;
    private ItemUnlocksEdit itemUnlocks;
    private MobileEdit mobile;
    private TriggerEdit trigger;
    private TriggerResult triggerResult;
    private SkillEdit skill;
    private VocationEdit vocation;
    private String logEntryDesc;
    private String logCompEntryDesc;
    protected PlayerEdit player;
    private BookEntryEdit pEntry;
    private String activeTag;
    private String activeProperty;
    protected BufferedReader bufferedReader;

    public Parser() {
        activeTag = "";
        activeProperty = "";
        logEntryDesc = "";
        logCompEntryDesc = "";
        out = new BroadcasterImp();
    }

    public Parser(AdventureEdit a) {
        adv = a;
        activeTag = "";
        activeProperty = "";
        logEntryDesc = "";
        logCompEntryDesc = "";
        out = new BroadcasterImp();
    }

    protected void readLine(String ln) {
        ln = ln.trim();
        for (int x = 0; x < ln.length();) {
            if (activeTag.equalsIgnoreCase("LOGINSCREEN")
                    || activeTag.equalsIgnoreCase("CURRENCY")
                    || activeTag.equalsIgnoreCase("ITEM")
                    || activeTag.equalsIgnoreCase("MOBILE")
                    || activeTag.equalsIgnoreCase("ROOM")
                    || activeTag.equalsIgnoreCase("PLAYER")
                    || activeTag.equalsIgnoreCase("ENTRY")
                    || activeTag.equalsIgnoreCase("TRIGGER")
                    || activeTag.equalsIgnoreCase("RESULT")
                    || activeTag.equalsIgnoreCase("SKILL")
                    || activeTag.equalsIgnoreCase("VOCATION")
                    || activeTag.equalsIgnoreCase("PVOCATION")) {
                if (ln.charAt(x) == '<') {
                    x = x + readTag(ln.substring(x));
                } else {
                    String data = readData(ln.substring(x));

                    int incX = data.length();
                    if (incX == 0) {
                        incX = 1;
                    }
                    x = x + incX;

                    commitProperty(data);
                }
            } else {
                if (ln.charAt(x) == '<') {
                    x = x + readTag(ln.substring(x));
                } else {
                    x++;
                }
            }
        }
    }

    private int readTag(String ln) {
        if (debug) {
            System.out.println("Reading tag " + ln);
        }
        int x = 1;
        String tag = "";
        while (x < ln.length() && ln.charAt(x) != '>') {
            tag = tag + ln.charAt(x);
            x++;
        }
        if (activeTag.equalsIgnoreCase("ITEM")) {
            readItemTag(tag);
        } else if (activeTag.equalsIgnoreCase("MOBILE")) {
            readMobileTag(tag);
        } else if (activeTag.equalsIgnoreCase("ROOM")) {
            readRoomTag(tag);
        } else if (activeTag.equalsIgnoreCase("TRIGGER")) {
            readTriggerTag(tag);
        } else if (activeTag.equalsIgnoreCase("RESULT")) {
            readResultTag(tag);
        } else if (activeTag.equalsIgnoreCase("PLAYER")) {
            readPlayerTag(tag);
        } else if (activeTag.equalsIgnoreCase("ENTRY")) {
            readEntryTag(tag);
        } else if (activeTag.equalsIgnoreCase("SKILL")) {
            readSkillTag(tag);
        } else if (activeTag.equalsIgnoreCase("VOCATION")) {
            readVocationTag(tag);
        } else if (activeTag.equalsIgnoreCase("PVOCATION")) {
            readPlayersVocationTag(tag);
        } else {
            if (tag.toUpperCase().startsWith("ADVENTURE")) {
                newAdventure(tag.substring(10));
            } else if (tag.equalsIgnoreCase("LOGINSCREEN")) {
                if (debug) {
                    System.out.println("Starting to read login screen.");
                }
                startReadingLoginScreen();
            } else if (tag.toUpperCase().startsWith("CURRENCY ")) {
                newCurrency(tag.substring(9));
            } else if (tag.toUpperCase().startsWith("ITEM ")) {
                newItem(tag.substring(5));
            } else if (tag.toUpperCase().startsWith("MOBILE ")) {
                newMobile(tag.substring(7));
            } else if (tag.toUpperCase().startsWith("TRIGGER ")) {
                newTrigger(tag.substring(8));
            } else if (tag.toUpperCase().startsWith("ROOM ")) {
                newRoom(tag.substring(5));
            } else if (tag.toUpperCase().startsWith("PLAYER ")) {
                newPlayer(tag.substring(7));
            } else if (tag.toUpperCase().startsWith("SKILL ")) {
                newSkill(tag.substring(6));
            } else if (tag.toUpperCase().startsWith("VOCATION ")) {
                newVocation(tag.substring(9));
            }
        }
        return x + 1;
    }

    private void readItemTag(String tag) {
        if (tag.toUpperCase().equals("NAME")) {
            activeProperty = "NAME";
        } else if (tag.toUpperCase().equals("DESCRIPTION")) {
            activeProperty = "DESCRIPTION";
        } else if (tag.toUpperCase().equals("TYPE")) {
            activeProperty = "TYPE";
        } else if (tag.toUpperCase().equals("TYPEMOD")) {
            activeProperty = "TYPEMOD";
        } else if (tag.toUpperCase().equals("CURRENCYVALUE")) {
            activeProperty = "CURRENCYVALUE";
        } else if (tag.toUpperCase().equals("CONSUMABLE")) {
            activeProperty = "CONSUMABLE";
        } else if (tag.toUpperCase().equals("USES")) {
            activeProperty = "USES";
        } else if (tag.toUpperCase().equals("TEMPORARY")) {
            activeProperty = "TEMPORARY";
        } else if (tag.toUpperCase().equals("TICKSREMAIN")) {
            activeProperty = "TICKSREMAIN";
        } else if (tag.toUpperCase().equals("LIGHTSOURCE")) {
            activeProperty = "LIGHTSOURCE";
        } else if (tag.toUpperCase().startsWith("ITEMUNLOCKS ")) {
            activeProperty = "ITEMUNLOCKS";

            int a = parseInt(readProperty(tag, "x"));
            int b = parseInt(readProperty(tag, "y"));
            int c = parseInt(readProperty(tag, "z"));

            itemUnlocks = new ItemUnlocksImp(a, b, c);
        } else if (tag.toUpperCase().equals("BOUND")) {
            activeProperty = "BOUND";
        } else if (tag.equalsIgnoreCase("/ITEM")) {
            activeProperty = "";
            activeTag = "";
            adv.getPlaceableManager().newItem(item);
            item = null;
        } else if (tag.equalsIgnoreCase("/ITEMUNLOCKS")) {
            activeProperty = "";
            item.addUnlocks(itemUnlocks);
            itemUnlocks = null;
        } else if (tag.startsWith("/")) {
            // End the property tag
            activeProperty = "";
        } else {
            activeTag = "";
            activeProperty = "";
        }
    }

    private void readMobileTag(String tag) {
        if (tag.toUpperCase().equals("NAME")) {
            activeProperty = "NAME";
        } else if (tag.toUpperCase().equals("DESCRIPTION")) {
            activeProperty = "DESCRIPTION";
        } else if (tag.toUpperCase().equals("LEVEL")) {
            activeProperty = "LEVEL";
        } else if (tag.toUpperCase().equals("HEALTH")) {
            activeProperty = "HEALTH";
        } else if (tag.toUpperCase().equals("ATTACK")) {
            activeProperty = "ATTACK";
        } else if (tag.toUpperCase().equals("DEFENCE")) {
            activeProperty = "DEFENCE";
        } else if (tag.toUpperCase().equals("SPEED")) {
            activeProperty = "SPEED";
        } else if (tag.toUpperCase().equals("LUCK")) {
            activeProperty = "LUCK";
        } else if (tag.toUpperCase().equals("AGGRO")) {
            activeProperty = "AGGRO";
        } else if (tag.toUpperCase().equals("DEAD")) {
            activeProperty = "DEAD";
        } else if (tag.toUpperCase().equals("IMMORTAL")) {
            activeProperty = "IMMORTAL";
        } else if (tag.toUpperCase().equals("VENDOR")) {
            activeProperty = "VENDOR";
        } else if (tag.toUpperCase().equals("VENDORMOD")) {
            activeProperty = "VENDORMOD";
        } else if (tag.toUpperCase().equals("CURRENCYAMOUNT")) {
            activeProperty = "CURRENCYAMOUNT";
        } else if (tag.toUpperCase().equals("LIGHTSOURCE")) {
            activeProperty = "LIGHTSOURCE";
        } else if (tag.toUpperCase().startsWith("ITEM ")) {
            activeProperty = "";
            int id = parseInt(readProperty(tag, "id"));
            Item newItem = adv.getPlaceableManager().getItem(id).cloneThis();
            mobile.addInventoryItem(newItem);
        } else if (tag.equalsIgnoreCase("/MOBILE")) {
            activeProperty = "";
            activeTag = "";
            mobile.setCurrencyType(adv.getCurrency());
            adv.getPlaceableManager().newMobile(mobile);
            mobile = null;
        } else if (tag.startsWith("/")) {
            // End the property tag
            activeProperty = "";
        } else {
            activeTag = "";
            activeProperty = "";
        }
    }

    private void readTriggerTag(String tag) {
        if (tag.toUpperCase().equals("NAME")) {
            activeProperty = tag.toUpperCase();
        } else if (tag.toUpperCase().equals("TRIGGEREDNAME")) {
            activeProperty = tag.toUpperCase();
        } else if (tag.toUpperCase().equals("DESCRIPTION")) {
            activeProperty = tag.toUpperCase();
        } else if (tag.toUpperCase().equals("VISIBLE")) {
            activeProperty = tag.toUpperCase();
        } else if (tag.toUpperCase().equals("LIMITEDUSES")) {
            activeProperty = tag.toUpperCase();
        } else if (tag.toUpperCase().equals("TOTALUSES")) {
            activeProperty = tag.toUpperCase();
        } else if (tag.toUpperCase().equals("DESCRIPTION")) {
            activeProperty = tag.toUpperCase();
        } else if (tag.toUpperCase().equals("LIGHTSOURCE")) {
            activeProperty = "LIGHTSOURCE";
        } else if (tag.toUpperCase().startsWith("RESULT ")) {
            activeProperty = "";
            newResult(tag);
        } else if (tag.equalsIgnoreCase("/TRIGGER")) {
            activeProperty = "";
            activeTag = "";
            trigger.setBroadcaster(out);
            adv.getPlaceableManager().newTrigger(trigger);
            trigger = null;
        } else if (tag.startsWith("/")) {
            // End the property tag
            activeProperty = "";
        }
    }

    private void readResultTag(String tag) {
        if (tag.equalsIgnoreCase("RESULTTEXT")) {
            activeProperty = tag.toUpperCase();
        } else if (tag.equalsIgnoreCase("LIMITEDUSES")) {
            activeProperty = tag.toUpperCase();
        } else if (tag.equalsIgnoreCase("PUBLIC")) {
            activeProperty = tag.toUpperCase();
        } else if (tag.equalsIgnoreCase("USES")) {
            activeProperty = tag.toUpperCase();
        } else if (tag.equalsIgnoreCase("MODWHAT")) {
            activeProperty = tag.toUpperCase();
        } else if (tag.equalsIgnoreCase("STRING")) {
            activeProperty = tag.toUpperCase();
        } else if (tag.equalsIgnoreCase("INT")) {
            activeProperty = tag.toUpperCase();
        } else if (tag.equalsIgnoreCase("ENTRYDESC")) {
            activeProperty = tag.toUpperCase();
        } else if (tag.equalsIgnoreCase("COMPENTRYDESC")) {
            activeProperty = tag.toUpperCase();
        } else if (tag.equalsIgnoreCase("X") || tag.equalsIgnoreCase("Y") || tag.equalsIgnoreCase("Z")) {
            activeProperty = tag.toUpperCase();
        } else if (tag.toUpperCase().startsWith("ITEM ")) {
            activeProperty = "";
            int id = parseInt(readProperty(tag, "id"));
            Item newItem = adv.getPlaceableManager().getItem(id).cloneThis();

            if (triggerResult.getType().equals("STRING")) {
                ((ResultString) triggerResult).setItem(newItem);
            } else if (triggerResult.getType().equals("SPAWNITEM")) {
                ((ResultSpawnItem) triggerResult).setItem(newItem);
            } else if (triggerResult.getType().equals("MODIFYPLAYER")) {
                ((ResultModifyPlayer) triggerResult).setItem(newItem);
            }
        } else if (tag.toUpperCase().startsWith("MOBILE ")) {
            activeProperty = "";
            int id = parseInt(readProperty(tag, "id"));
            Mobile newMob = adv.getPlaceableManager().getMobile(id).cloneThis();

            if (triggerResult.getType().equals("STRING")) {
                ((ResultString) triggerResult).setMobile(newMob);
            } else if (triggerResult.getType().equals("SPAWNMOBILE")) {
                ((ResultSpawnMobile) triggerResult).setMobile(newMob);
            }
        } else if (tag.toUpperCase().startsWith("SKILL ")) {
            activeProperty = "";
            int id = parseInt(readProperty(tag, "id"));
            Skill newSkill = adv.getSkillManager().getSkill(id).cloneThis();

            if (triggerResult.getType().equals("STRING")) {
                ((ResultString) triggerResult).setSkill(newSkill);
            } else if (triggerResult.getType().equals("MODIFYPLAYER")) {
                ((ResultModifyPlayer) triggerResult).setSkill(newSkill);
            }
        } else if (tag.toUpperCase().startsWith("TRIGGER ")) {
            activeProperty = "";
            int id = parseInt(readProperty(tag, "id"));
            Trigger newTrig = adv.getPlaceableManager().getTrigger(id).cloneThis();

            if (triggerResult.getType().equals("STRING")) {
                ((ResultString) triggerResult).setTrigger(newTrig);
            } else if (triggerResult.getType().equals("SPAWNTRIGGER")) {
                ((ResultSpawnTrigger) triggerResult).setTrigger(newTrig);
            }
        } else if (tag.toUpperCase().startsWith("CONDITION ")) {
            readConditionTag(tag);
        } else if (tag.equalsIgnoreCase("/RESULT")) {
            addResult();
        }
    }

    private void readConditionTag(String tag) {
        activeProperty = "";
        String type = readProperty(tag, "type");
        String dependant = readProperty(tag, "dependant");
        String strval = readProperty(tag, "strval");
        boolean not = Boolean.parseBoolean(readProperty(tag, "not"));
        TriggerCondition cond;
        if (dependant.equals("PLAYER")) {
            int intval = parseInt(readProperty(tag, "intval"));
            int quantity = parseInt(readProperty(tag, "quantity"));

            cond = new PlayerCondition(type, intval, quantity, strval, not);
        } else if (dependant.equals("ROOM")) {
            int intval = parseInt(readProperty(tag, "intval"));
            int quantity = parseInt(readProperty(tag, "quantity"));

            cond = new RoomCondition(type, intval, quantity, strval, not);
        } else {
            cond = new StringCondition(type, strval, not);
        }

        triggerResult.addCondition(cond);
    }

    private void addResult() {
        activeProperty = "";
        activeTag = "TRIGGER";
        if (triggerResult.getType().equalsIgnoreCase("MODIFYPLAYER")) {
            if (((ResultModifyPlayer) triggerResult).getModifyWhat().equalsIgnoreCase("ADDLOG")) {
                ResultModifyPlayer rmp = ((ResultModifyPlayer) triggerResult);
                BookEntry e = new BookEntryImp(rmp.getIntMod(), rmp.getStrMod(),
                        logEntryDesc, logCompEntryDesc);
                rmp.setEntry(e);
            }
        }
        logEntryDesc = "";
        logCompEntryDesc = "";
        triggerResult.setCurrencyType(adv.getCurrency());
        trigger.addResult(triggerResult);
        triggerResult = null;
    }

    private void readRoomTag(String tag) {
        if (tag.toUpperCase().equals("NARRATIVE")) {
            activeProperty = "NARRATIVE";
        } else if (tag.toUpperCase().equals("TITLE")) {
            activeProperty = "TITLE";
        } else if (tag.toUpperCase().equals("DESCRIPTION")) {
            activeProperty = "DESCRIPTION";
        } else if (tag.toUpperCase().equals("BLOCKED")) {
            activeProperty = "BLOCKED";
        } else if (tag.toUpperCase().equals("CLOSED")) {
            activeProperty = "CLOSED";
        } else if (tag.toUpperCase().equals("LOCKED")) {
            activeProperty = "LOCKED";
        } else if (tag.toUpperCase().equals("CURRENCYAMOUNT")) {
            activeProperty = "CURRENCYAMOUNT";
        } else if (tag.toUpperCase().equals("SPAWNLEVEL")) {
            activeProperty = "SPAWNLEVEL";
        } else if (tag.toUpperCase().equals("LOWLIGHT")) {
            activeProperty = "LOWLIGHT";
        } else if (tag.toUpperCase().equals("TICKSUNTILREPOP")) {
            activeProperty = "TICKSUNTILREPOP";
        } else if (tag.toUpperCase().startsWith("ITEM ")) {
            activeProperty = "";
            int id = parseInt(readProperty(tag, "id"));
            room.addItem(adv.getPlaceableManager().getItem(id));
        } else if (tag.toUpperCase().startsWith("MOBILE ")) {
            activeProperty = "";
            int id = parseInt(readProperty(tag, "id"));
            room.addMobile(adv.getPlaceableManager().getMobile(id));
        } else if (tag.toUpperCase().startsWith("TRIGGER ")) {
            activeProperty = "";
            int id = parseInt(readProperty(tag, "id"));
            room.addTrigger(adv.getPlaceableManager().getTrigger(id));
        } else if (tag.equalsIgnoreCase("/ROOM")) {
            activeProperty = "";
            activeTag = "";
            room.setCurrencyType(adv.getCurrency());
            room.captureInitialState();
            adv.getRoomManager().newRoom(room, room.x(), room.y(), room.z());
            room = null;
        } else if (tag.startsWith("/")) {
            // End the property tag
            activeProperty = "";
        } else {
            activeTag = "";
            activeProperty = "";
        }
    }

    private void readSkillTag(String tag) {
        if (tag.toUpperCase().equals("SYNONYMS")) {
            activeProperty = tag.toUpperCase();
        } else if (tag.toUpperCase().equals("CATEGORY")) {
            activeProperty = tag.toUpperCase();
        } else if (tag.toUpperCase().equals("DESCRIPTION")) {
            activeProperty = tag.toUpperCase();
        } else if (tag.toUpperCase().equals("ATTACKFLAG")) {
            activeProperty = tag.toUpperCase();
        } else if (tag.toUpperCase().equals("ATTACKDESC")) {
            activeProperty = tag.toUpperCase();
        } else if (tag.toUpperCase().equals("MAINSTAT")) {
            activeProperty = tag.toUpperCase();
        } else if (tag.toUpperCase().equals("COOLDOWN")) {
            activeProperty = tag.toUpperCase();
        } else if (tag.toUpperCase().equals("REQUIRESCONCENTRATION")) {
            activeProperty = tag.toUpperCase();
        } else if (tag.toUpperCase().equals("DIFFICULTY")) {
            activeProperty = tag.toUpperCase();
        } else if (tag.toUpperCase().equals("SPECIALCOST")) {
            activeProperty = tag.toUpperCase();
        } else if (tag.toUpperCase().equals("LEVELLEARNED")) {
            activeProperty = tag.toUpperCase();
        } else if (tag.toUpperCase().equals("ONFLOOR")) {
            activeProperty = tag.toUpperCase();
        } else if (tag.toUpperCase().startsWith("ITEM ")) {
            activeProperty = "";
            int id = parseInt(readProperty(tag, "id"));
            Item newItem = adv.getPlaceableManager().getItem(id).cloneThis();
            ((ConjureItem) skill).setItem(newItem);
        } else if (tag.toUpperCase().startsWith("DICE ")) {
            activeProperty = "";
            int num = parseInt(readProperty(tag, "num"));
            int sides = parseInt(readProperty(tag, "sides"));
            skill.setDice(num, sides);
        } else if (tag.toUpperCase().startsWith("ITEMNEEDED ")) {
            activeProperty = "";
            int id = parseInt(readProperty(tag, "id"));
            int quantity = parseInt(readProperty(tag, "quantity"));

            int[][] itemsNeededOld = skill.getItemsNeeded();
            int[][] itemsNeededNew = new int[itemsNeededOld.length + 1][2];

            for (int c = 0; c < itemsNeededOld.length; c++) {
                itemsNeededNew[c][0] = itemsNeededOld[c][0];
                itemsNeededNew[c][1] = itemsNeededOld[c][1];
            }
            itemsNeededNew[itemsNeededOld.length][0] = id;
            itemsNeededNew[itemsNeededOld.length][1] = quantity;

            skill.setItemsNeeded(itemsNeededNew);
        } else if (tag.equalsIgnoreCase("/SKILL")) {
            activeProperty = "";
            activeTag = "";
            adv.getSkillManager().newSkill(skill);
            skill = null;
        } else if (tag.startsWith("/")) {
            // End the property tag
            activeProperty = "";
        } else {
            activeTag = "";
            activeProperty = "";
        }
    }

    private void readVocationTag(String tag) {
        if (tag.toUpperCase().equals("NAME")) {
            activeProperty = tag.toUpperCase();
        } else if (tag.toUpperCase().equals("DESCRIPTION")) {
            activeProperty = tag.toUpperCase();
        } else if (tag.toUpperCase().equals("BASEATTACK")) {
            activeProperty = tag.toUpperCase();
        } else if (tag.toUpperCase().equals("BASEDEFENCE")) {
            activeProperty = tag.toUpperCase();
        } else if (tag.toUpperCase().equals("BASEINTEL")) {
            activeProperty = tag.toUpperCase();
        } else if (tag.toUpperCase().equals("BASESPEED")) {
            activeProperty = tag.toUpperCase();
        } else if (tag.toUpperCase().equals("BASELUCK")) {
            activeProperty = tag.toUpperCase();
        } else if (tag.toUpperCase().equals("INCATTACK")) {
            activeProperty = tag.toUpperCase();
        } else if (tag.toUpperCase().equals("INCDEFENCE")) {
            activeProperty = tag.toUpperCase();
        } else if (tag.toUpperCase().equals("INCINTEL")) {
            activeProperty = tag.toUpperCase();
        } else if (tag.toUpperCase().equals("INCSPEED")) {
            activeProperty = tag.toUpperCase();
        } else if (tag.toUpperCase().equals("INCLUCK")) {
            activeProperty = tag.toUpperCase();
        } else if (tag.toUpperCase().startsWith("SKILL ")) {
            activeProperty = "";
            int id = parseInt(readProperty(tag, "id"));
            Skill newSkill = ((SkillEdit) adv.getSkillManager().getSkill(id)).cloneThis();
            vocation.learnSkill(newSkill);
        } else if (tag.equalsIgnoreCase("/VOCATION")) {
            activeProperty = "";
            activeTag = "";
            adv.getVocationManager().newVocation(vocation);
            vocation = null;
        } else if (tag.startsWith("/")) {
            // End the property tag
            activeProperty = "";
        } else {
            activeTag = "";
            activeProperty = "";
        }
    }

    private void readPlayerTag(String tag) {
        if (tag.toUpperCase().equals("NAME")) {
            activeProperty = tag.toUpperCase();
        } else if (tag.toUpperCase().equals("RACE")) {
            activeProperty = tag.toUpperCase();
        } else if (tag.toUpperCase().equals("DESCRIPTION")) {
            activeProperty = tag.toUpperCase();
        } else if (tag.toUpperCase().equals("LEVEL")) {
            activeProperty = tag.toUpperCase();
        } else if (tag.toUpperCase().equals("MAXHEALTH")) {
            activeProperty = tag.toUpperCase();
        } else if (tag.toUpperCase().equals("HEALTH")) {
            activeProperty = tag.toUpperCase();
        } else if (tag.toUpperCase().equals("MAXSPECIAL")) {
            activeProperty = tag.toUpperCase();
        } else if (tag.toUpperCase().equals("SPECIAL")) {
            activeProperty = tag.toUpperCase();
        } else if (tag.toUpperCase().equals("ATTACK")) {
            activeProperty = tag.toUpperCase();
        } else if (tag.toUpperCase().equals("DEFENCE")) {
            activeProperty = tag.toUpperCase();
        } else if (tag.toUpperCase().equals("INTELLIGENCE")) {
            activeProperty = tag.toUpperCase();
        } else if (tag.toUpperCase().equals("SPEED")) {
            activeProperty = tag.toUpperCase();
        } else if (tag.toUpperCase().equals("LUCK")) {
            activeProperty = tag.toUpperCase();
        } else if (tag.toUpperCase().equals("EXPERIENCE")) {
            activeProperty = tag.toUpperCase();
        } else if (tag.toUpperCase().equals("CURRENCYAMOUNT")) {
            activeProperty = tag.toUpperCase();
        } else if (tag.toUpperCase().equals("X")) {
            activeProperty = tag.toUpperCase();
        } else if (tag.toUpperCase().equals("Y")) {
            activeProperty = tag.toUpperCase();
        } else if (tag.toUpperCase().equals("Z")) {
            activeProperty = tag.toUpperCase();
        } else if (tag.toUpperCase().equals("SX")) {
            activeProperty = tag.toUpperCase();
        } else if (tag.toUpperCase().equals("SY")) {
            activeProperty = tag.toUpperCase();
        } else if (tag.toUpperCase().equals("SZ")) {
            activeProperty = tag.toUpperCase();
        } else if (tag.toUpperCase().equals("GENERAL")) {
            activeProperty = tag.toUpperCase();
        } else if (tag.toUpperCase().equals("TRADE")) {
            activeProperty = tag.toUpperCase();
        } else if (tag.toUpperCase().equals("NEWBIE")) {
            activeProperty = tag.toUpperCase();
        } else if (tag.toUpperCase().equals("OOC")) {
            activeProperty = tag.toUpperCase();
        } else if (tag.toUpperCase().equals("SUPPRESSTICK")) {
            activeProperty = tag.toUpperCase();
        } else if (tag.toUpperCase().equals("PASSWORD")) {
            activeProperty = tag.toUpperCase();
        } else if (tag.toUpperCase().equals("SUPERADMIN")) {
            activeProperty = tag.toUpperCase();
        } else if (tag.toUpperCase().equals("ADMIN")) {
            activeProperty = tag.toUpperCase();
        } else if (tag.toUpperCase().startsWith("ITEM ")) {
            activeProperty = "";
            int id = parseInt(readProperty(tag, "id"));
            Item newItem = adv.getPlaceableManager().getItem(id).cloneThis();

            int uses = parseInt(readProperty(tag, "usesLeft"));
            ((ItemEdit) newItem).setRemainingUses(uses);
            player.giveItem(newItem);
        } else if (tag.toUpperCase().startsWith("WEAPONEQ ")) {
            activeProperty = "";
            int id = parseInt(readProperty(tag, "id"));
            Item newItem = adv.getPlaceableManager().getItem(id).cloneThis();
            player.giveItem(newItem);
            player.equipWeapon(newItem);
        } else if (tag.toUpperCase().startsWith("OFFHANDEQ ")) {
            activeProperty = "";
            int id = parseInt(readProperty(tag, "id"));
            Item newItem = adv.getPlaceableManager().getItem(id).cloneThis();
            player.giveItem(newItem);
            player.equipOffhand(newItem);
        } else if (tag.toUpperCase().startsWith("HEADEQ ")) {
            activeProperty = "";
            int id = parseInt(readProperty(tag, "id"));
            Item newItem = adv.getPlaceableManager().getItem(id).cloneThis();
            player.giveItem(newItem);
            player.equipHelm(newItem);
        } else if (tag.toUpperCase().startsWith("CHESTEQ ")) {
            activeProperty = "";
            int id = parseInt(readProperty(tag, "id"));
            Item newItem = adv.getPlaceableManager().getItem(id).cloneThis();
            player.giveItem(newItem);
            player.equipChest(newItem);
        } else if (tag.toUpperCase().startsWith("FEETEQ ")) {
            activeProperty = "";
            int id = parseInt(readProperty(tag, "id"));
            Item newItem = adv.getPlaceableManager().getItem(id).cloneThis();
            player.giveItem(newItem);
            player.equipBoots(newItem);
        } else if (tag.toUpperCase().startsWith("ENTRY ")) {
            activeProperty = "";
            newEntry(tag);
        } else if (tag.toUpperCase().startsWith("VOCATION ")) {
            activeTag = "PVOCATION";
            activeProperty = "";
            int id = parseInt(readProperty(tag, "id"));
            vocation = new VocationImp(id);
        } else if (tag.startsWith("/")) {
            // End the property tag
            activeProperty = "";
        } else {
            activeTag = "";
            activeProperty = "";
        }
    }

    private void readPlayersVocationTag(String tag) {
        if (tag.toUpperCase().equals("NAME")) {
            activeProperty = tag.toUpperCase();
        } else if (tag.toUpperCase().equals("DESCRIPTION")) {
            activeProperty = tag.toUpperCase();
        } else if (tag.toUpperCase().equals("BASEATTACK")) {
            activeProperty = tag.toUpperCase();
        } else if (tag.toUpperCase().equals("BASEDEFENCE")) {
            activeProperty = tag.toUpperCase();
        } else if (tag.toUpperCase().equals("BASEINTEL")) {
            activeProperty = tag.toUpperCase();
        } else if (tag.toUpperCase().equals("BASESPEED")) {
            activeProperty = tag.toUpperCase();
        } else if (tag.toUpperCase().equals("BASELUCK")) {
            activeProperty = tag.toUpperCase();
        } else if (tag.toUpperCase().equals("INCATTACK")) {
            activeProperty = tag.toUpperCase();
        } else if (tag.toUpperCase().equals("INCDEFENCE")) {
            activeProperty = tag.toUpperCase();
        } else if (tag.toUpperCase().equals("INCINTEL")) {
            activeProperty = tag.toUpperCase();
        } else if (tag.toUpperCase().equals("INCSPEED")) {
            activeProperty = tag.toUpperCase();
        } else if (tag.toUpperCase().equals("INCLUCK")) {
            activeProperty = tag.toUpperCase();
        } else if (tag.toUpperCase().startsWith("SKILL ")) {
            activeProperty = "";
            int id = parseInt(readProperty(tag, "id"));
            Skill newSkill = ((SkillEdit) adv.getSkillManager().getSkill(id)).cloneThis();
            System.out.println("Setting playerManager - players == null?" + (players == null));
            newSkill.setPlayerManager(players);
            newSkill.setBroadcaster(out);

            if (debug) {
                System.out.println("Creating skill #" + id + ", PlayerManager = null?: " + (players == null));
            }
            vocation.learnSkill(newSkill);
        } else if (tag.equalsIgnoreCase("/VOCATION")) {
            activeProperty = "";
            activeTag = "PLAYER";
            System.out.println("Vocation set: " + ((Vocation) vocation).getName());
            player.setVocation((Vocation) vocation.cloneThis());
            vocation = null;
        } else if (tag.startsWith("/")) {
            // End the property tag
            activeProperty = "";
        } else {
            activeTag = "PLAYER";
            activeProperty = "";
        }
    }

    private void readEntryTag(String tag) {
        if (tag.equalsIgnoreCase("TITLE")) {
            activeProperty = tag.toUpperCase();
        } else if (tag.equalsIgnoreCase("DESCRIPTION")) {
            activeProperty = tag.toUpperCase();
        } else if (tag.equalsIgnoreCase("COMPDESC")) {
            activeProperty = tag.toUpperCase();
        } else if (tag.equalsIgnoreCase("/ENTRY")) {
            addEntry();
        } else {
            activeProperty = "";
        }
    }

    private void addEntry() {
        activeProperty = "";
        activeTag = "PLAYER";

        player.newLogEntry((BookEntry) pEntry);
        pEntry = null;
    }

    private String readData(String ln) {
        int x = 0;
        String data = "";
        while (x < ln.length() && ln.charAt(x) != '<') {
            data = data + ln.charAt(x);
            x++;
        }
        if (x == ln.length()) {
            // Read the NEXT line..
            try {
                data = data + "\n" + readData(bufferedReader.readLine());
            } catch (Exception e) {
                System.err.println(e);
            }
        }

        return data;
    }

    private String readProperty(String advTag, String val) {
        int tagStart = advTag.indexOf(val + "='");

        if (tagStart != -1) {
            int start = tagStart + val.length() + 2;

            int end = start;

            while (advTag.charAt(end) != '\'') {
                end++;
            }

            return advTag.substring(start, end);
        } else {
            return "";
        }
    }

    private boolean propertyExists(String advTag, String val) {
        return advTag.contains(val);
    }

    private void commitProperty(String data) {
        data = data.replace("&#38;", "&").replace("&#60;", "<").replace("&#62;", ">");
        if (activeTag.equalsIgnoreCase("loginscreen")) {
            commitLoginScreenData(data);
        } else if (activeTag.equalsIgnoreCase("item")) {
            commitItemProperty(data);
        } else if (activeTag.equalsIgnoreCase("mobile")) {
            commitMobileProperty(data);
        } else if (activeTag.equalsIgnoreCase("room")) {
            commitRoomProperty(data);
        } else if (activeTag.equalsIgnoreCase("trigger")) {
            commitTriggerProperty(data);
        } else if (activeTag.equalsIgnoreCase("result")) {
            commitResultProperty(data);
        } else if (activeTag.equalsIgnoreCase("player")) {
            commitPlayerProperty(data);
        } else if (activeTag.equalsIgnoreCase("entry")) {
            commitEntryProperty(data);
        } else if (activeTag.equalsIgnoreCase("skill")) {
            commitSkillProperty(data);
        } else if (activeTag.equalsIgnoreCase("vocation")) {
            commitVocationProperty(data);
        } else if (activeTag.equalsIgnoreCase("pvocation")) {
            commitVocationProperty(data);
        }
    }

    private void commitLoginScreenData(String data) {
        activeTag = "";
        adv.setLoginScreen(data);
        if (debug) {
            System.out.println("Login screen:" + data);
        }
    }

    private void commitItemProperty(String data) {
        if (activeProperty.equalsIgnoreCase("name")) {
            item.setName(data);
        } else if (activeProperty.equalsIgnoreCase("description")) {
            item.setDescription(data);
        } else if (activeProperty.equalsIgnoreCase("type")) {
            item.setItemType(data);
        } else if (activeProperty.equalsIgnoreCase("typemod")) {
            item.setModifier(parseInt(data));
        } else if (activeProperty.equalsIgnoreCase("currencyvalue")) {
            item.setCurrencyValue(parseInt(data));
        } else if (activeProperty.equalsIgnoreCase("consumable")) {
            item.setConsumable(Boolean.parseBoolean(data));
        } else if (activeProperty.equalsIgnoreCase("uses")) {
            item.setTotalUses(parseInt(data));
        } else if (activeProperty.equalsIgnoreCase("temporary")) {
            item.setTemporary(Boolean.parseBoolean(data));
        } else if (activeProperty.equalsIgnoreCase("ticksremain")) {
            item.setTicksRemaining(parseInt(data));
        } else if (activeProperty.equalsIgnoreCase("lightsource")) {
            item.setLightSource(Boolean.parseBoolean(data));
        } else if (activeProperty.equalsIgnoreCase("itemunlocks")) {
            itemUnlocks.setDir(data.charAt(0));
        } else if (activeProperty.equalsIgnoreCase("bound")) {
            item.setBound(Boolean.parseBoolean(data));
        }
    }

    private void commitMobileProperty(String data) {
        if (activeProperty.equalsIgnoreCase("name")) {
            mobile.setName(data);
        } else if (activeProperty.equalsIgnoreCase("description")) {
            mobile.setDescription(data);
        } else if (activeProperty.equalsIgnoreCase("level")) {
            mobile.setLevel(parseInt(data));
        } else if (activeProperty.equalsIgnoreCase("attack")) {
            mobile.setAttack(parseInt(data));
        } else if (activeProperty.equalsIgnoreCase("defence")) {
            mobile.setDefence(parseInt(data));
        } else if (activeProperty.equalsIgnoreCase("speed")) {
            mobile.setSpeed(parseInt(data));
        } else if (activeProperty.equalsIgnoreCase("luck")) {
            mobile.setLuck(parseInt(data));
        } else if (activeProperty.equalsIgnoreCase("health")) {
            mobile.setMaxHealth(parseInt(data));
        } else if (activeProperty.equalsIgnoreCase("currencyAmount")) {
            mobile.setCurrencyAmount(parseInt(data));
        } else if (activeProperty.equalsIgnoreCase("lightsource")) {
            mobile.setLightSource(Boolean.parseBoolean(data));
        } else if (activeProperty.equalsIgnoreCase("aggro")) {
            if (data.equalsIgnoreCase("true")) {
                mobile.setAggro(true);
            } else {
                mobile.setAggro(false);
            }
        } else if (activeProperty.equalsIgnoreCase("dead")) {
            if (data.equalsIgnoreCase("true")) {
                mobile.setDead(true);
            } else {
                mobile.setDead(false);
            }
        } else if (activeProperty.equalsIgnoreCase("immortal")) {
            if (data.equalsIgnoreCase("true")) {
                mobile.setImmortal(true);
            } else {
                mobile.setImmortal(false);
            }
        } else if (activeProperty.equalsIgnoreCase("vendor")) {
            if (data.equalsIgnoreCase("true")) {
                mobile.setVendor(true);
            } else {
                mobile.setVendor(false);
            }
        } else if (activeProperty.equalsIgnoreCase("vendorMod")) {
            mobile.setVendorModifier(parseDouble(data));
        }
    }

    private void commitTriggerProperty(String data) {
        if (activeProperty.equalsIgnoreCase("name")) {
            trigger.setName(data);
        } else if (activeProperty.equalsIgnoreCase("description")) {
            trigger.setDescription(data);
        } else if (activeProperty.equalsIgnoreCase("triggeredname")) {
            trigger.setTriggeredName(data);
        } else if (activeProperty.equalsIgnoreCase("visible")) {
            trigger.setVisible(Boolean.parseBoolean(data));
        } else if (activeProperty.equalsIgnoreCase("LIMITEDUSES")) {
            trigger.setLimitedUses(Boolean.parseBoolean(data));
        } else if (activeProperty.equalsIgnoreCase("TOTALUSES")) {
            trigger.setTotalUses(parseInt(data));
        } else if (activeProperty.equalsIgnoreCase("lightsource")) {
            trigger.setLightSource(Boolean.parseBoolean(data));
        }
    }

    private void commitResultProperty(String data) {
        if (activeProperty.equalsIgnoreCase("RESULTTEXT")) {
            triggerResult.setResultText(data);
        } else if (activeProperty.equalsIgnoreCase("PUBLIC")) {
            triggerResult.setPublicResult(Boolean.parseBoolean(data));
        } else if (activeProperty.equalsIgnoreCase("LIMITEDUSES")) {
            triggerResult.setLimitedUses(Boolean.parseBoolean(data));
        } else if (activeProperty.equalsIgnoreCase("USES")) {
            triggerResult.setUses(parseInt(data));
        } else if (activeProperty.equalsIgnoreCase("modwhat")) {
            if (triggerResult.getType().equals("MODIFYPLAYER")) {
                ((ResultModifyPlayer) triggerResult).setModifyWhat(data);
            } else if (triggerResult.getType().equals("MODIFYROOM")) {
                ((ResultModifyRoom) triggerResult).setModifyWhat(data);
            }
        } else if (activeProperty.equalsIgnoreCase("string")) {
            if (triggerResult.getType().equals("MODIFYPLAYER")) {
                ((ResultModifyPlayer) triggerResult).setStringMod(data);
            } else if (triggerResult.getType().equals("MODIFYROOM")) {
                ((ResultModifyRoom) triggerResult).setStringMod(data);
            }
        } else if (activeProperty.equalsIgnoreCase("int")) {
            if (triggerResult.getType().equals("MODIFYPLAYER")) {
                ((ResultModifyPlayer) triggerResult).setIntMod(parseInt(data));
            } else if (triggerResult.getType().equals("MODIFYROOM")) {
                ((ResultModifyRoom) triggerResult).setIntMod(parseInt(data));
            }
        } else if (activeProperty.equalsIgnoreCase("x")) {
            if (triggerResult.getType().equals("MOVEPLAYER")) {
                ((ResultMovePlayer) triggerResult).setDestX(parseInt(data));
            }
        } else if (activeProperty.equalsIgnoreCase("y")) {
            if (triggerResult.getType().equals("MOVEPLAYER")) {
                ((ResultMovePlayer) triggerResult).setDestY(parseInt(data));
            }
        } else if (activeProperty.equalsIgnoreCase("z")) {
            if (triggerResult.getType().equals("MOVEPLAYER")) {
                ((ResultMovePlayer) triggerResult).setDestZ(parseInt(data));
            }
        } else if (activeProperty.equalsIgnoreCase("entrydesc")) {
            logEntryDesc = data;
        } else if (activeProperty.equalsIgnoreCase("compentrydesc")) {
            logCompEntryDesc = data;
        }
    }

    private void commitRoomProperty(String data) {
        if (activeProperty.equalsIgnoreCase("title")) {
            room.setTitle(data);
        } else if (activeProperty.equalsIgnoreCase("description")) {
            room.setDescription(data);
        } else if (activeProperty.equalsIgnoreCase("closed")) {
            room.setClosed(data.toUpperCase());
        } else if (activeProperty.equalsIgnoreCase("locked")) {
            room.setLocked(data.toUpperCase());
        } else if (activeProperty.equalsIgnoreCase("blocked")) {
            room.setBlocked(data.toUpperCase());
        } else if (activeProperty.equalsIgnoreCase("currencyAmount")) {
            room.setCurrencyContents(parseInt(data));
        } else if (activeProperty.equalsIgnoreCase("ticksuntilrepop")) {
            room.setRepopTickCount(parseInt(data));
        } else if (activeProperty.equalsIgnoreCase("spawnlevel")) {
            room.setSpawnLevel(parseInt(data));
        } else if (activeProperty.equalsIgnoreCase("lowlight")) {
            if (data.equalsIgnoreCase("true")) {
                room.setLowLight(true);
            } else {
                room.setLowLight(false);
            }
        }
    }

    private void commitSkillProperty(String data) {
        if (activeProperty.equalsIgnoreCase("synonyms")) {
            if (debug) {
                System.out.println(data.split(" ").length);
            }
            skill.setSynonyms(data.split(" "));
        } else if (activeProperty.equalsIgnoreCase("category")) {
            skill.setCategory(data);
        } else if (activeProperty.equalsIgnoreCase("description")) {
            skill.setDescription(data);
        } else if (activeProperty.equalsIgnoreCase("attackFlag")) {
            skill.setActionFlag(parseInt(data));
        } else if (activeProperty.equalsIgnoreCase("attackDesc")) {
            skill.setAttackDesc(data);
        } else if (activeProperty.equalsIgnoreCase("mainStat")) {
            skill.setMainStat(parseInt(data));
        } else if (activeProperty.equalsIgnoreCase("cooldown")) {
            skill.setCooldown(parseInt(data));
        } else if (activeProperty.equalsIgnoreCase("specialcost")) {
            skill.setSpecialReq(parseInt(data));
        } else if (activeProperty.equalsIgnoreCase("levelLearned")) {
            skill.setLevelToLearn(parseInt(data));
        } else if (activeProperty.equalsIgnoreCase("requiresConcentration")) {
            skill.setRequiresConcentration(Boolean.parseBoolean(data));
        } else if (activeProperty.equalsIgnoreCase("difficulty")) {
            skill.setDifficulty(parseInt(data));
        } else if (activeProperty.equalsIgnoreCase("onFloor")) {
            ((ConjureItem) skill).setOnFloor(Boolean.parseBoolean(data));
        }
    }

    private void commitVocationProperty(String data) {
        if (activeProperty.equalsIgnoreCase("name")) {
            vocation.setName(data);
            System.out.println("Setting vocation " + ((Vocation) vocation).getName());
        } else if (activeProperty.equalsIgnoreCase("description")) {
            vocation.setDescription(data);
        } else if (activeProperty.equalsIgnoreCase("baseAttack")) {
            vocation.setBaseAttack(parseInt(data));
        } else if (activeProperty.equalsIgnoreCase("baseDefence")) {
            vocation.setBaseDefence(parseInt(data));
        } else if (activeProperty.equalsIgnoreCase("baseIntel")) {
            vocation.setBaseIntel(parseInt(data));
        } else if (activeProperty.equalsIgnoreCase("baseSpeed")) {
            vocation.setBaseSpeed(parseInt(data));
        } else if (activeProperty.equalsIgnoreCase("baseLuck")) {
            vocation.setBaseLuck(parseInt(data));
        } else if (activeProperty.equalsIgnoreCase("incAttack")) {
            vocation.setChanceIncAttack(parseDouble(data));
        } else if (activeProperty.equalsIgnoreCase("incDefence")) {
            vocation.setChanceIncDefence(parseDouble(data));
        } else if (activeProperty.equalsIgnoreCase("incIntel")) {
            vocation.setChanceIncIntel(parseDouble(data));
        } else if (activeProperty.equalsIgnoreCase("incSpeed")) {
            vocation.setChanceIncSpeed(parseDouble(data));
        } else if (activeProperty.equalsIgnoreCase("incLuck")) {
            vocation.setChanceIncLuck(parseDouble(data));
        }
    }

    private void commitPlayerProperty(String data) {
        if (activeProperty.equalsIgnoreCase("name")) {
            player.setName(data);
        } else if (activeProperty.equalsIgnoreCase("title")) {
            player.setTitle(data);
        } else if (activeProperty.equalsIgnoreCase("level")) {
            player.setLevel(parseInt(data));
        } else if (activeProperty.equalsIgnoreCase("maxhealth")) {
            player.setMaxHealth(parseInt(data));
        } else if (activeProperty.equalsIgnoreCase("health")) {
            player.setHealth(parseInt(data));
        } else if (activeProperty.equalsIgnoreCase("maxspecial")) {
            player.setMaxSpecial(parseInt(data));
        } else if (activeProperty.equalsIgnoreCase("special")) {
            player.setSpecial(parseInt(data));
        } else if (activeProperty.equalsIgnoreCase("attack")) {
            player.setAttack(parseInt(data));
        } else if (activeProperty.equalsIgnoreCase("defence")) {
            player.setDefence(parseInt(data));
        } else if (activeProperty.equalsIgnoreCase("intelligence")) {
            player.setIntelligence(parseInt(data));
        } else if (activeProperty.equalsIgnoreCase("speed")) {
            player.setSpeed(parseInt(data));
        } else if (activeProperty.equalsIgnoreCase("luck")) {
            player.setLuck(parseInt(data));
        } else if (activeProperty.equalsIgnoreCase("experience")) {
            player.setExperience(parseInt(data));
        } else if (activeProperty.equalsIgnoreCase("currencyAmount")) {
            player.setCurrencyAmount(parseInt(data));
        } else if (activeProperty.equalsIgnoreCase("x")) {
            player.setX(parseInt(data));
        } else if (activeProperty.equalsIgnoreCase("y")) {
            player.setY(parseInt(data));
        } else if (activeProperty.equalsIgnoreCase("z")) {
            player.setZ(parseInt(data));
        } else if (activeProperty.equalsIgnoreCase("sx")) {
            player.setSpawnX(parseInt(data));
        } else if (activeProperty.equalsIgnoreCase("sy")) {
            player.setSpawnY(parseInt(data));
        } else if (activeProperty.equalsIgnoreCase("sz")) {
            player.setSpawnZ(parseInt(data));
        } else if (activeProperty.equalsIgnoreCase("password")) {
            player.setPassword(data);
        } else if (activeProperty.equalsIgnoreCase("admin")) {
            player.setAdmin(Boolean.parseBoolean(data));
        } else if (activeProperty.equalsIgnoreCase("superAdmin")) {
            player.setSuperAdmin(Boolean.parseBoolean(data));
        } else if (activeProperty.equalsIgnoreCase("general")) {
            if (data.equalsIgnoreCase("true")) {
                ((Player) player).subscribeTo("general");
            }
        } else if (activeProperty.equalsIgnoreCase("ooc")) {
            if (data.equalsIgnoreCase("true")) {
                ((Player) player).subscribeTo("ooc");
            }
        } else if (activeProperty.equalsIgnoreCase("newbie")) {
            if (data.equalsIgnoreCase("true")) {
                ((Player) player).subscribeTo("newbie");
            }
        } else if (activeProperty.equalsIgnoreCase("trade")) {
            if (data.equalsIgnoreCase("true")) {
                ((Player) player).subscribeTo("trade");
            }
        } else if (activeProperty.equalsIgnoreCase("suppresstick")) {
            if (data.equalsIgnoreCase("true")) {
                player.setSuppressTick(true);
            } else {
                player.setSuppressTick(false);
            }
        }
    }

    private void commitEntryProperty(String data) {
        if (activeProperty.equalsIgnoreCase("title")) {
            pEntry.setTitle(data);
        } else if (activeProperty.equalsIgnoreCase("description")) {
            pEntry.setDescription(data);
        } else if (activeProperty.equalsIgnoreCase("compdesc")) {
            pEntry.setCompleteDescription(data);
        }
    }

    private void newAdventure(String advTag) {
        String name = readProperty(advTag, "name");
        String desc = readProperty(advTag, "description");
        double version = Double.parseDouble(readProperty(advTag, "version"));
        if (debug) {
            System.out.println(readProperty(advTag, "softwareVersion"));
        }

        double softVersion = 1;;
        if (propertyExists(advTag, "softwareVersion")) {
            softVersion = Double.parseDouble(readProperty(advTag, "softwareVersion"));
        }

        if (debug) {
            System.out.println("SoftVersion:" + softVersion);
        }

        String author = readProperty(advTag, "author");
        int x = parseInt(readProperty(advTag, "sx"));
        int y = parseInt(readProperty(advTag, "sy"));
        int z = parseInt(readProperty(advTag, "sz"));

        this.adv = new AdventureImp(name, softVersion);
        adv.setDescription(desc);
        adv.setVersion(version);
        adv.setAuthor(author);
        adv.setStartArea(x, y, z);
    }

    private void startReadingLoginScreen() {
        activeTag = "LOGINSCREEN";
    }

    private void newCurrency(String cTag) {
        activeTag = "";
        activeProperty = "";

        String statusID = readProperty(cTag, "statusID");
        String singular = readProperty(cTag, "singular");
        String singularDark = readProperty(cTag, "singularDark");
        String plural = readProperty(cTag, "plural");
        String pluralDark = readProperty(cTag, "pluralDark");

        adv.setCurrency(new CurrencyImp(statusID, singular, plural, singularDark, pluralDark));
    }

    private void newItem(String iTag) {
        activeTag = "ITEM";
        int id = parseInt(readProperty(iTag, "id"));
        item = new ItemImp(id);
    }

    private void newMobile(String mTag) {
        activeTag = "MOBILE";
        int id = parseInt(readProperty(mTag, "id"));
        mobile = new MobileImp(id);
    }

    private void newTrigger(String rTag) {
        activeTag = "TRIGGER";
        int id = parseInt(readProperty(rTag, "id"));
        trigger = new TriggerImp(id);
    }

    private void newResult(String rTag) {
        activeTag = "RESULT";
        String resultType = readProperty(rTag, "type");

        if (resultType.equals("STRING")) {
            triggerResult = new ResultString();
        } else if (resultType.equals("MODIFYROOM")) {
            triggerResult = new ResultModifyRoom();
        } else if (resultType.equals("MODIFYPLAYER")) {
            triggerResult = new ResultModifyPlayer((Adventure) adv);
        } else if (resultType.equals("MOVEPLAYER")) {
            triggerResult = new ResultMovePlayer();
        } else if (resultType.equals("SPAWNITEM")) {
            triggerResult = new ResultSpawnItem();
        } else if (resultType.equals("SPAWNMOBILE")) {
            triggerResult = new ResultSpawnMobile();
        } else if (resultType.equals("SPAWNTRIGGER")) {
            triggerResult = new ResultSpawnTrigger();
        }
    }

    private void newRoom(String rTag) {
        activeTag = "ROOM";
        int x = parseInt(readProperty(rTag, "x"));
        int y = parseInt(readProperty(rTag, "y"));
        int z = parseInt(readProperty(rTag, "z"));
        room = new RoomImp(x, y, z);
    }

    private void newSkill(String sTag) {
        activeTag = "SKILL";
        String id = readProperty(sTag, "id");
        String skillType = readProperty(sTag, "type");

        if (skillType.equals("DAMAGETARGET")) {
            skill = new SingleTargetDamage((Adventure) adv, parseInt(id));
        } else if (skillType.equals("HEALTARGET")) {
            skill = new SingleTargetHeal((Adventure) adv, parseInt(id));
        } else if (skillType.equals("CONJUREITEM")) {
            skill = new ConjureItem((Adventure) adv, parseInt(id));
        }
    }

    private void newVocation(String vTag) {
        activeTag = "VOCATION";
        int id = parseInt(readProperty(vTag, "id"));
        vocation = new VocationImp(id);
    }

    private void newPlayer(String pTag) {
        activeTag = "PLAYER";
        int id = parseInt(readProperty(pTag, "id"));
        player = new PlayerImp(id);
    }

    private void newEntry(String eTag) {
        activeTag = "ENTRY";
        int id = parseInt(readProperty(eTag, "id"));
        boolean complete = Boolean.parseBoolean(readProperty(eTag, "complete"));
        pEntry = new BookEntryImp(id, complete);
    }

    protected int parseInt(String input) {
        input = input.trim();
        try {
            return Integer.parseInt(input);
        } catch (NumberFormatException e) {
            return 0;
        }
    }

    protected double parseDouble(String input) {
        input = input.trim();
        try {
            return Double.parseDouble(input);
        } catch (NumberFormatException e) {
            return 0;
        }
    }

    protected String formatForSaving(String input) {
        return input.replace("<", "&#60;").replace(">", "&#62;").replace("&", "&#38;");
    }
}
